home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / RAYTRACE.ZIP / HT.BAK < prev    next >
Encoding:
Text File  |  1994-06-11  |  21.9 KB  |  733 lines

  1. //  Test of height mapping
  2. //  Started: 06/05/94
  3. //  Author: Leo Sutic - Watcom conversion by Lary Myers
  4. //  Module: HT.C (Original module: RAYCAST.CPP)
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <malloc.h>
  9. #include <mem.h>
  10. #include <string.h>
  11. #include <dos.h>
  12. #include <time.h>
  13. #include <io.h>
  14. #include <fcntl.h>
  15. #include <sys\stat.h>
  16. #include <math.h>
  17. #include "loadpcx.h"
  18.  
  19. typedef unsigned long   ULONG;
  20. typedef unsigned short  UINT;
  21. typedef unsigned char   UCHAR;
  22.  
  23. #define USE_ASSEMBLER   1   // Set to 0 to use C routines
  24.  
  25. #define MAX_ANGLE       1280
  26. #define COLUMN_AMOUNT   2
  27. #define HALF_SCREEN     (320/COLUMN_AMOUNT)
  28.  
  29. #define M_PI        3.14159265358979323846
  30. #define RAYLENGTH           160
  31. #define MAXLENGTH           220
  32. #define WORLDX              320
  33. #define WORLDY              200
  34. #define WORLDSIZE           65535
  35.  
  36. // The altitude of the viewer. (Above ground)
  37. #define USERALT             32
  38.  
  39. // How far to look out over the horizon, the large the value the slower it is
  40. #define HORIZON_DISTANCE    90
  41.  
  42. // How fast the viewer moves, the larger the value, the faster but also the
  43. // more choppier the screen will be.
  44. #define VIEWER_SPEED        3
  45.  
  46.  
  47. #define ABS(a)   ((a < 0) ? -a : a)
  48. #define SGN(a)   ((a < 0) ? -1 : 1)
  49.  
  50.  
  51. #define KEYBD               0x9     // Keyboard interrupt
  52. #define RIGHT_ARROW_KEY     77
  53. #define UP_ARROW_KEY        72
  54. #define LEFT_ARROW_KEY      75
  55. #define DOWN_ARROW_KEY      80
  56. #define MINUS_KEY           74
  57. #define PLUS_KEY            78
  58. #define NUMBER_5_KEY        76
  59. #define ESCAPE_KEY          1
  60. #define PGUP_KEY            73
  61. #define PGDN_KEY            81
  62. #define B_KEY               48
  63. #define C_KEY               46
  64. #define F_KEY               33
  65. #define I_KEY               23
  66. #define R_KEY               19
  67. #define S_KEY               31
  68. #define W_KEY               17
  69. #define NUM_1_KEY           2
  70. #define NUM_2_KEY           3
  71. #define NUM_3_KEY           4
  72. #define NUM_4_KEY           5
  73. #define NUM_5_KEY           6
  74. #define NUM_6_KEY           7
  75. #define NUM_7_KEY           8
  76. #define NUM_8_KEY           9
  77. #define NUM_9_KEY           10
  78.  
  79.     UCHAR   scanCode;
  80.     UCHAR   KeyPressed;
  81.     UCHAR   MiniKey;
  82.     UCHAR   Keys[128];
  83.  
  84.     short   TopRow;
  85.     short   HorizonTilt;
  86.     short   CurrentAlt;
  87.     UCHAR   *Video;
  88.     UCHAR   *Buffer;
  89.     UCHAR   *World;
  90.     UCHAR   *Color;
  91.     UCHAR   *Sky;
  92.     UCHAR   *BackDrop;
  93.     short   USERX;
  94.     short   USERY;
  95.     short   USERA;
  96.     short   xPosns[MAX_ANGLE];
  97.     short   yPosns[MAX_ANGLE];
  98.     long    sine[MAX_ANGLE];
  99.     long    cosine[MAX_ANGLE];
  100.     short   startpostable[MAXLENGTH+50];
  101.     short   startposOrg[MAXLENGTH+50];
  102.     unsigned short OffsetTable[200];
  103.     long    RangeTable[HORIZON_DISTANCE * 2];
  104.  
  105.     short   RowTable[200];
  106.     short   ColorTable[200];
  107.     short   UserAlt;
  108.     UCHAR   Used[200];
  109.     struct  VgaPalette PalBuf[256];
  110.  
  111.     void    (__interrupt __far *oldvec)();
  112.     void    __interrupt __far myInt();
  113.  
  114. #if USE_ASSEMBLER
  115.     void    CopyVertical(void);
  116.     void    FillLinearBuffer(short startpos,short length);
  117.     void    FillUsedBuffer(void);
  118. #endif
  119.  
  120. extern  UCHAR   colordat[];
  121.  
  122.  
  123. //=============================================================================
  124. // Keyboard interrupt 9
  125. //=============================================================================
  126. void __interrupt __far myInt(void)
  127. {
  128.   register char x;
  129.  
  130. // oldvec();    // Use when screen captures are wanted - calls orig vector
  131.  
  132. scanCode = inp(0x60); // read keyboard data port
  133. x = inp(0x61);
  134. outp(0x61, (x | 0x80));
  135. outp(0x61, x);
  136. outp(0x20, 0x20);
  137.  
  138. Keys[scanCode & 127] = 1;
  139. KeyPressed = 1;
  140. if (scanCode & 128)
  141.     {
  142.     Keys[scanCode & 127] = 0;
  143.     KeyPressed = 0;
  144.     }
  145. else
  146.     MiniKey = 1;
  147.  
  148. }
  149.  
  150. //=============================================================================
  151. // Sets the 256 color palette. pBuf contains the RGB values to set
  152. //=============================================================================
  153. void SetPalette(UCHAR *pbuf)
  154. {
  155.     short     cnt,index;
  156.  
  157. cnt = 256;
  158. index = 0;
  159.  
  160. while (cnt-- > 0)
  161.     {
  162.     outp(0x3c8,index++);
  163.     outp(0x3c9,*pbuf++);
  164.     outp(0x3c9,*pbuf++);
  165.     outp(0x3c9,*pbuf++);
  166.     }
  167.  
  168. }
  169.  
  170. //=============================================================================
  171. //
  172. //=============================================================================
  173. void SetVideoMode(short Mode)
  174. {
  175.     union REGPACK regs;
  176.  
  177. memset(®s,0,sizeof(union REGPACK));  // Make sure segments are zero
  178. regs.w.ax = Mode;                       // Set the mode we want to go to
  179. intr(0x10,®s);                       // Use INT 10h to set mode
  180.  
  181. }
  182.  
  183. //=============================================================================
  184. //
  185. //=============================================================================
  186. short LoadFiles(void)
  187. {
  188.     FILE    *Data;
  189.     UCHAR   *bPtr;
  190.     struct  PcxPix  PcxBuf;
  191.  
  192. if (load_pcx("ht.pcx",&PcxBuf,PalBuf) != pcx_ok)
  193.     return(1);
  194.  
  195. BackDrop = PcxBuf.image;
  196.  
  197. if (load_pcx("sky.pcx",&PcxBuf,PalBuf) != pcx_ok)
  198.     return(2);
  199.  
  200. Sky = PcxBuf.image;
  201.  
  202. if (load_pcx("Altitude.pcx",&PcxBuf,PalBuf) != pcx_ok)
  203.     return(3);
  204.  
  205. bPtr = PcxBuf.image;
  206.  
  207. World = malloc(65536);                  // Get a buffer for entire area
  208. if (World == NULL)
  209.     return(3);
  210.  
  211. memmove(World,bPtr,64000);
  212. memmove(&World[64000],bPtr,1536);   // Then duplicate some rows
  213. free(bPtr);
  214.  
  215.  
  216. if (load_pcx("Color.pcx",&PcxBuf,PalBuf) != pcx_ok)
  217.     return(4);
  218.  
  219. bPtr = PcxBuf.image;
  220.  
  221. Color = malloc(65536);                  // Get a buffer for the entire area
  222.  
  223. if (Color == NULL)
  224.     return(4);
  225.  
  226. memmove(Color,bPtr,64000);
  227. memmove(&Color[64000],bPtr,1536);      // Then duplicate some rows
  228. free(bPtr);
  229.  
  230. return(0);
  231. }
  232.  
  233. //=============================================================================
  234. // Calculate a circular area around the center origin that will be the
  235. // coordinates for our viewing area. These coordinates will then be added to
  236. // the viewers current X,Y coordinates to give us the endpoints of the line
  237. // we will cast.
  238. //=============================================================================
  239. void SetViewDistance(void)
  240. {
  241.     short   Angle;
  242.  
  243. for (Angle = 0; Angle < MAX_ANGLE; Angle++)
  244.     {
  245.     xPosns[Angle] = (cosine[Angle] * HORIZON_DISTANCE) >> 14;
  246.     yPosns[Angle] = (sine[Angle] * HORIZON_DISTANCE) >> 14;
  247.     }
  248.  
  249.  
  250. }
  251.  
  252. //=============================================================================
  253. // Setup our two arrays for quicker sine and cosine calculations.
  254. //=============================================================================
  255. void InitSinCos(void)
  256. {
  257.     int     a;
  258.     float   A;
  259.  
  260. for (a = 0;a < MAX_ANGLE;a++)
  261.     {
  262.     A = a;                                  // Get angle in a float
  263.     A = (A * M_PI) / (MAX_ANGLE/2);         // Convert degrees to radians
  264.     sine[a] = sin(A) * 16384;               // Get fixed point sine 2^14
  265.     cosine[a] = cos(A) * 16384;             // Get fixed point cosine 2^14
  266.     }
  267.  
  268. SetViewDistance();
  269.  
  270. }
  271.  
  272. //=============================================================================
  273. //
  274. //=============================================================================
  275. void InitStartPosTable(void)
  276. {
  277.     int     i,distance;
  278.     long    ht;
  279.  
  280. ht = (long)16 << 14;                            // Set fixed point height
  281.  
  282. for (distance = 1; distance < (HORIZON_DISTANCE*2); distance++)
  283.     {
  284.     RangeTable[distance] = ht / distance;   // Setup height range table
  285.     }
  286.  
  287. for (i = 1;i < (RAYLENGTH+50);i++)
  288.     {
  289.     startposOrg[i] = startpostable[i] = 500 / i;    // Used for rows on screen
  290.     startpostable[i] += HorizonTilt;
  291.     }
  292.  
  293. for (i = 0; i < 200; i++)
  294.     OffsetTable[i] = i * 320;               // Faster video offset lookups
  295.  
  296. }
  297.  
  298.     long    OldPos;
  299.     long    HighRow;
  300.     long    CurrentColumn;
  301.     long    CurrentAngle;
  302.     UCHAR   CurrentColor;
  303.  
  304. //=============================================================================
  305. //
  306. //=============================================================================
  307. void DrawLine(void)
  308. {
  309.     short           i,x1,y1,x2,y2;
  310.     short           length,startpos;
  311.     long            height;
  312.     short           d,ax,ay,sx,sy,dx,dy,yOff;
  313.     short           BegRow,NumRows;
  314.     unsigned short  offset;
  315.     unsigned char   c;
  316.     short           *sptPtr;
  317.     UCHAR           *bPtr;
  318.  
  319.  
  320. OldPos = 199;                       // Used to speed up drawing
  321. HighRow = 200;                      // Marker of highest row drawn to
  322.  
  323. offset = OffsetTable[USERY] + USERX; // Current location in color map
  324. CurrentColor = Color[offset];        // Current color at viewer location
  325.  
  326. #if USE_ASSEMBLER
  327.     FillUsedBuffer();
  328. #else
  329.     memset(&Used[100],CurrentColor,100);  // Pre-fill buffer to cover holes????
  330. #endif
  331.  
  332. x1 = USERX + xPosns[CurrentAngle];  // Get our most distance coordinates
  333. y1 = USERY + yPosns[CurrentAngle];
  334. x2 = USERX;                         // Put viewer coordinates into temps
  335. y2 = USERY;
  336.  
  337. offset = y1 * WORLDX + x1;          // Calculate offset into buffers
  338. dx = x2-x1;                         // Get our delta X
  339. ax = abs(dx) << 1;                  // Get our delta X * 2 for difference checks
  340. sx = SGN(dx);                       // Get 1 or -1 based on sign of delta X
  341. dy = y2-y1;                         // Get our delta Y
  342. ay = abs(dy) << 1;                  // Delta Y * 2 for difference checks
  343. sy = SGN(dy);                       // Get 1 or -1 based on sign of delta Y
  344. yOff = WORLDX;                      // Assume a positive sign and get offset
  345. if (sy < 0)                         // If negative direction then
  346.     yOff = -WORLDX;                 // use a minus offset (this is a row offset)
  347.  
  348. if (ax > ay)                        // Is our X difference greater than Y diff?
  349.     {
  350.     d = ay - (ax >> 1);             // Yes, calc the error term to use
  351.     length = abs(dx);                   // Length of the line to plot
  352.     sptPtr = &startpostable[length];    // Use pointer to avoid indexing
  353.     for (i = length; i > 0; i--)
  354.         {
  355.         CurrentColor = Color[offset];   // Color to use for this segment of column
  356.         // Height is calculated by taking the height of the current location
  357.         // subtracting the viewer height, then multiplying by the pre-calc'd
  358.         // distance perspective table divided by the current length of the
  359.         // line. See how RangeTable is setup for further details. The table is
  360.         // used so a faster multiply can be done vs a slower divide by length
  361.         // for each unit of the line.
  362.         height = ((World[offset] - UserAlt) * RangeTable[i]) >> 14;
  363.  
  364.         // Perspective transform takes a predetermined height for the length
  365.         // of the line and subtracts the calculated height above. This gives
  366.         // us an actual height for the location we are currently examining.
  367.         // Note below that startpos is actual a delta height greater than
  368.         // the last height we calculated. OldPos is used to remember the last
  369.         // height we found.
  370.         startpos = *sptPtr - height;
  371.         sptPtr--;
  372.  
  373.     #if USE_ASSEMBLER
  374.         FillLinearBuffer(startpos,i);
  375.     #else
  376.         if (startpos > OldPos)          // Are we beyond the last height?
  377.             {
  378.             // Are we in bounds for the screen vertical height?
  379.             if (startpos > 0 && startpos < 200 && OldPos < 200)
  380.                 {
  381.                 if (i < 10)             // Check our length and fill from
  382.                     {                   // the bottom up
  383.                     NumRows = 200 - OldPos;  // for the last height remembered.
  384.                     BegRow = 199;
  385.                     }
  386.                 else
  387.                     {
  388.                     // Otherwise start with current minus last as number of rows
  389.                     NumRows = startpos - OldPos;
  390.                     BegRow = startpos;
  391.                     }
  392.  
  393.                 BegRow -= NumRows;      // We want to build downward not up.
  394.                 if (BegRow < 0)         // If starting row went negative
  395.                     {
  396.                     NumRows += BegRow;  // Adjust the number of rows
  397.                     BegRow = 0;         // And start at top of column
  398.                     }
  399.  
  400.                 if (BegRow < HighRow)   // Keep our high water mark updated
  401.                     HighRow = BegRow;
  402.  
  403.  
  404.                 // Copy the color into a buffer which will later be used
  405.                 // to display the vertical column.
  406.                 memset(&Used[BegRow],CurrentColor,NumRows);
  407.                 }
  408.             }
  409.     #endif
  410.  
  411.         OldPos = startpos;          // Now update our remembered height
  412.  
  413.         if( d >= 0 )                // Check error term to see if Y coordinate
  414.             {                       // needs to be adjusted
  415.             offset += yOff;         // Bump buffer offset to next row
  416.             d -= ax;                // and reset our error term
  417.             }
  418.  
  419.         offset += sx;               // Bump buffer offset to next column
  420.         d += ay;                    // and adjust our error term
  421.         }
  422.     }
  423. else        // Here if the Y difference is >= the X difference
  424.     {
  425.     d = ax - (ay >> 1);
  426.     length = abs(dy);
  427.     sptPtr = &startpostable[length];    // Use pointer to avoid indexing
  428.     for (i = length; i > 0; i--)
  429.         {
  430.         CurrentColor = Color[offset];
  431.         height = ((World[offset] - UserAlt) * RangeTable[i]) >> 14;
  432.  
  433.         // Perspective transform
  434.         startpos = *sptPtr - height; // Get perspective height for this distance
  435.         sptPtr--;
  436.  
  437.     #if USE_ASSEMBLER
  438.         FillLinearBuffer(startpos,i);
  439.     #else
  440.         if (startpos > OldPos)
  441.             {
  442.             if (startpos > 0 && startpos < 200 && OldPos < 200)
  443.                 {
  444.                 if (i < 10)
  445.                     {
  446.                     NumRows = 200 - OldPos;
  447.                     BegRow = 199;
  448.                     }
  449.                 else
  450.                     {
  451.                     NumRows = startpos - OldPos;
  452.                     BegRow = startpos;
  453.                     }
  454.  
  455.                 BegRow -= NumRows;
  456.                 if (BegRow < 0)
  457.                     {
  458.                     NumRows += BegRow;
  459.                     BegRow = 0;
  460.                     }
  461.                 if (BegRow < HighRow)
  462.                     HighRow = BegRow;
  463.                 memset(&Used[BegRow],CurrentColor,NumRows);
  464.                 }
  465.             }
  466.     #endif
  467.  
  468.  
  469.         OldPos = startpos;          // Used to speed up rendering.
  470.  
  471.         if( d >= 0 )
  472.             {
  473.             offset += sx;
  474.             d -= ay;
  475.             }
  476.         offset += yOff;
  477.         d += ax;
  478.         }
  479.     }
  480.  
  481. // Now copy our buffer to the vertical column of the screen
  482.  
  483. #if USE_ASSEMBLER
  484.     CopyVertical();
  485. #else
  486.     bPtr = Buffer + OffsetTable[HighRow] + CurrentColumn;
  487.     for (i = HighRow; i < 200; i++)
  488.         {
  489.         c = Used[i];
  490.         *bPtr = c;
  491.         bPtr[1] = c;
  492.         bPtr += 320;
  493.         }
  494. #endif
  495.  
  496. }
  497.  
  498.  
  499. //=============================================================================
  500. //
  501. //=============================================================================
  502. void ShowScreen(void)
  503. {
  504.  
  505. memmove(Video,Buffer,51200);
  506.  
  507. }
  508.  
  509. //=============================================================================
  510. //
  511. //=============================================================================
  512. void ShowBackDrop(void)
  513. {
  514.  
  515. memmove(Video,BackDrop,64000);
  516.  
  517. }
  518.  
  519.  
  520.  
  521. //=============================================================================
  522. //
  523. //=============================================================================
  524. void DrawSkyRange(short Angle,short column,short wt,short rows)
  525. {
  526.     UCHAR   *SkyPtr,*BufPtr;
  527.  
  528. SkyPtr = Sky + Angle;           // Get offset into Sky buffer
  529. BufPtr = Buffer + column;       // Video buffer column to start with
  530. while (rows-- > 0)
  531.     {
  532.     memmove(BufPtr,SkyPtr,wt);  // Move width from Sky to buffer
  533.     BufPtr += 320;              // Next row of Video buffer
  534.     SkyPtr += 320;              // Next row of Sky buffer
  535.     }
  536.  
  537. }
  538.  
  539. //=============================================================================
  540. //
  541. //=============================================================================
  542. void DrawView(void)
  543. {
  544.     short   column,Angle,px,py;
  545.     short   Alt1,Alt2;
  546.     unsigned short offset;
  547.  
  548.  
  549. // Draw the sky in 2 sections, first start out with the column of the sky
  550. // for our current angle and draw as much as possible, then start with column
  551. // zero of the sky and draw any remaining columns
  552.  
  553. Angle = USERA % 320;                    // Get starting column of sky buffer
  554. px = 320 - Angle;                       // Get width of sky we can draw
  555. if (px)
  556.     DrawSkyRange(Angle,0,px,150);       // Draw 150 rows of width
  557.  
  558. py = 320 - px;                          // Now get remaining width we need
  559. if (py)
  560.     DrawSkyRange(0,px,py,150);          // And draw from column 0 of sky
  561.  
  562. Angle = USERA + 160;                    // Angle plus half the screen
  563. if (Angle >= MAX_ANGLE)                 // Check if beyond max angle range
  564.     Angle -= MAX_ANGLE;                 // and bring back down into range
  565.  
  566. px = USERX + ((cosine[Angle] * 6) >> 14);
  567. py = USERY + ((sine[Angle] * 6) >> 14);
  568. offset = (py * WORLDX) + px;
  569. Alt1 = World[offset];                   // Get the height alittle in front
  570.  
  571.  
  572. offset = (USERY * WORLDX) + USERX;      // Get the offset into our world
  573. px = World[offset];                     // Get the altitude of the viewer
  574.  
  575. if (px > CurrentAlt)                    // Are we higher than our viewer height?
  576.     UserAlt = px + CurrentAlt;          // Yes, set to new height
  577. else
  578.     UserAlt = CurrentAlt;               // Otherwise stay at viewer height
  579.  
  580. if (Alt1 > UserAlt)                     // Is height in front of us higher?
  581.     UserAlt = Alt1 + CurrentAlt;        // Yes, set to new height
  582.  
  583. CurrentAngle = USERA;                   // Start with left side of screen
  584.  
  585. for (CurrentColumn = 0; CurrentColumn < 320; CurrentColumn += COLUMN_AMOUNT)
  586.     {
  587.     DrawLine();                         // Draw current vertical column
  588.     CurrentAngle += COLUMN_AMOUNT;      // Next Angle on the screen
  589.     if (CurrentAngle >= MAX_ANGLE)      // Check if we wrapped around
  590.         CurrentAngle -= MAX_ANGLE;
  591.     }
  592.  
  593. ShowScreen();                           // Copy buffer to screen
  594.  
  595. }
  596.  
  597. //=============================================================================
  598. //
  599. //=============================================================================
  600. void DrawScreen(void)
  601. {
  602.     short   done,Angle,i;
  603.     short   SpinAngle;
  604.  
  605. memset(Buffer,0,64000);
  606. done = 0;
  607. SpinAngle = MAX_ANGLE >> 5;
  608.  
  609. while (!done)
  610.     {
  611.     DrawView();
  612.  
  613.     if (Keys[ESCAPE_KEY])
  614.         break;
  615.  
  616.     if (Keys[UP_ARROW_KEY])
  617.         {
  618.         Angle = USERA + HALF_SCREEN;
  619.         if (Angle >= MAX_ANGLE) Angle -= MAX_ANGLE;
  620.  
  621.         USERX = USERX + ((cosine[Angle] * VIEWER_SPEED) >> 14);
  622.         USERY = USERY + ((sine[Angle] * VIEWER_SPEED) >> 14);
  623.         USERX = USERX % WORLDX;
  624.         USERY = USERY % WORLDY;
  625.         }
  626.  
  627.     if (Keys[DOWN_ARROW_KEY])
  628.         {
  629.         Angle = USERA + HALF_SCREEN + (MAX_ANGLE/2);
  630.         if (Angle >= MAX_ANGLE) Angle -= MAX_ANGLE;
  631.  
  632.         USERX = USERX + ((cosine[Angle] * VIEWER_SPEED) >> 14);
  633.         USERY = USERY + ((sine[Angle] * VIEWER_SPEED) >> 14);
  634.         USERX %= WORLDX;
  635.         USERY %= WORLDY;
  636.         }
  637.  
  638.     if (Keys[LEFT_ARROW_KEY])
  639.         {
  640.         USERA = USERA - SpinAngle;
  641.         if (USERA < 0) USERA += MAX_ANGLE;
  642.         }
  643.  
  644.     if (Keys[RIGHT_ARROW_KEY])
  645.         {
  646.         USERA = USERA + SpinAngle;
  647.         if (USERA >= MAX_ANGLE) USERA -= MAX_ANGLE;
  648.         }
  649.  
  650.     if (Keys[PGUP_KEY])
  651.         {
  652.         if (HorizonTilt > 4)
  653.             {
  654.             HorizonTilt--;
  655.             for (i = 0; i < (RAYLENGTH+50); i++)
  656.                 startpostable[i] = startposOrg[i] + HorizonTilt;
  657.  
  658.             }
  659.         }
  660.  
  661.     if (Keys[PGDN_KEY])
  662.         {
  663.         if (HorizonTilt < 90)
  664.             {
  665.             HorizonTilt++;
  666.             for (i = 0; i < (RAYLENGTH+50); i++)
  667.                 startpostable[i] = startposOrg[i] + HorizonTilt;
  668.             }
  669.         }
  670.  
  671.     if (Keys[MINUS_KEY])
  672.         {
  673.         if (CurrentAlt > 8)
  674.             CurrentAlt--;
  675.  
  676.         }
  677.  
  678.     if (Keys[PLUS_KEY])
  679.         {
  680.         if (CurrentAlt < 100)
  681.             CurrentAlt++;
  682.         }
  683.  
  684.     }
  685.  
  686. }
  687.  
  688. //=============================================================================
  689. //
  690. //=============================================================================
  691. void main(short argc,char **argv)
  692. {
  693.     short   result;
  694.  
  695. HorizonTilt = 80;                       // Initialize our Horizon
  696. CurrentAlt = USERALT;                   // And default altitude
  697. InitSinCos();                           // Build our trig tables
  698. InitStartPosTable();                    // and Height to Row tables
  699. result = LoadFiles();                   // Load the pictures
  700. if (result)
  701.     {
  702.     printf("Error: %d while loading pictures.\n",result);
  703.     return;
  704.     }
  705.  
  706. Buffer = malloc(64000);                 // Init the buffer we'll draw to
  707. if (Buffer == NULL)
  708.     {
  709.     printf("Not enough memory.\n");
  710.     return;
  711.     }
  712.  
  713. USERX=160;                              // Starting X,Y coordinates
  714. USERY=100;
  715. USERA=960;                              // Starting angle.
  716.  
  717. Video = (UCHAR *)0xA0000;               // Address of VGA screen
  718. oldvec=_dos_getvect(KEYBD);             // Get the current keyboard vector
  719. _dos_setvect(KEYBD,myInt);              // And replace it with ours
  720.  
  721. SetVideoMode(0x13);                     // Switch to 320x200 256 color mode
  722. SetPalette((UCHAR *)PalBuf);            // And set our palette
  723. ShowBackDrop();                         // Show the main screen image
  724. DrawScreen();                           // Show terrain and allow moving
  725.  
  726. SetVideoMode(0x03);                     // Back to text color 80 mode
  727.  
  728. _dos_setvect(KEYBD,oldvec);             // Put back the old keyboard vector
  729.  
  730. }
  731.  
  732.  
  733.